﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace winS.Unity
{
    /// <summary>
    /// 轮盘赌算法的抽象实现
    /// </summary>
    public class Roulette<T> : IEnumerable<KeyValuePair<T, float>>
    {
        /// <summary>
        /// 当前赌注数
        /// </summary>
        public int betCount => betPairList.Count;
        /// <summary>
        /// 当前总点数
        /// </summary>
        public float totalPoints { get; protected set; }

        private readonly List<KeyValuePair<T, float>> betPairList;

        public Roulette()
        {
            betPairList = new List<KeyValuePair<T, float>>();
        }
        public Roulette(int capacity)
        {
            betPairList = new List<KeyValuePair<T, float>>(capacity);
        }
        public Roulette(Dictionary<T, float> dictionary) : this(dictionary.Count)
        {
            foreach (var pair in dictionary) AddBet(pair);
        }
        public Roulette(IList<T> bets, IList<float> points)
        {
            int betCount = bets.Count;
            if (betCount != points.Count) throw new Exception($"[{nameof(Roulette<T>)}] 赌注和点数的数量必须一致, {nameof(bets)} 的数量为 {bets.Count}, 而 {nameof(points)} 的数量却为 {points.Count}");
            betPairList = new List<KeyValuePair<T, float>>(betCount);
            for (int i = 0; i < betCount; i++) AddBet(bets[i], points[i]);
        }

        protected Roulette(Roulette<T> otherRoulette)
        {
            List<KeyValuePair<T, float>> sourceBetsPairList = otherRoulette.betPairList;
            int count = sourceBetsPairList.Count;
            betPairList = new List<KeyValuePair<T, float>>(count);
            for (int i = 0; i < count; i++) AddBet(sourceBetsPairList[i]);
        }

        /// <summary>
        /// 获取一个赌注
        /// </summary>
        public T Get()
        {
            if (betPairList.Count != 0)
            {
                float randomPoint = totalPoints * Random.Float01();
                float accumulatePoint = 0f;
                foreach (var pair in betPairList)
                {
                    accumulatePoint += pair.Value;
                    if (accumulatePoint < randomPoint) continue;
                    return pair.Key;
                }
            }
            return default;
        }
        public void Clear()
        {
            totalPoints = 0f;
            betPairList.Clear();
        }
        /// <summary>
        /// 添加赌注
        /// </summary>
        public void AddBet(T bet, float point)
        {
            AddBet(new KeyValuePair<T, float>(bet, point));
        }
        /// <summary>
        /// 添加赌注
        /// </summary>
        public void AddBet(KeyValuePair<T, float> betPair)
        {
            betPairList.Add(betPair);
            totalPoints += betPair.Value;
        }
        /// <summary>
        /// 移除赌注
        /// </summary>
        public bool RemoveBet(T bet)
        {
            int index = betPairList.FindIndex(betPair => betPair.Key.Equals(bet));
            if (index < 0) return false;
            RemoveBetAt(index);
            return true;
        }
        /// <summary>
        /// 移除指定索引的赌注
        /// </summary>
        public void RemoveBetAt(int index)
        {
            KeyValuePair<T, float> betPair = betPairList[index];
            betPairList.RemoveAt(index);
            totalPoints -= betPair.Value;
        }

        IEnumerator<KeyValuePair<T, float>> IEnumerable<KeyValuePair<T, float>>.GetEnumerator()
        {
            return betPairList.GetEnumerator();
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return betPairList.GetEnumerator();
        }
    }
}